<template>
  <view>
    <template v-if="props.filterable && props.options.length > 9">
      <view class="search">
        <image class="icon" src="@/assets/icon-search-placeholder-fill.png" />
        <less-input
          class="search-input"
          placeholder="搜索选项"
          v-model="keywords"
          @update:model-value="emitKeywordChanged"
          :maxlength="10"
        />
      </view>
      <view
        class="empty"
        v-if="keywords.length > 0 && searchOptions.length == 0"
      >
        <image class="image" src="@/assets/search-empty.png" />
        <view class="text">
          没有与“
          <view class="keywords">{{ keywords }}</view>
          ”匹配的结果
        </view>
      </view>
      <view
        class="grid-select search-select"
        :style="{
          gridTemplateColumns: `repeat(${props.columns}, 1fr)`,
        }"
        v-if="searchOptions.length > 0"
      >
        <view
          v-for="option in searchOptions"
          :key="getValue(option)"
          class="option"
          :class="{ selected: isSelected(option) }"
          @click="onClick(option)"
        >
          {{ getLabel(option) }}
        </view>
      </view>
    </template>
    <view
      class="grid-select"
    >
      <view
        v-for="(option, index) in datalist"
        :key="getValue(option)"
        class="option"
        :class="{ selected: isSelected(option) }"
        @click="onClick(option)"
      >
        {{ getLabel(option) }}
      </view>
    </view>
  </view>
</template>

<script lang="ts" setup>
import LessInput from "@/components/less-input/index.vue";
import { useDebounce } from "@/hooks/core/useDebounce";
import { computed, ref } from "vue";

interface OptionType {
  label: string;
  value: any;
}

// columns
const props = withDefaults(
  defineProps<{
    modelValue: any;
    options: OptionType[];
    multiple?: boolean;
    multipleLimit?: number; //时多选限制
    columns?: number;
    labelProp?: string;
    valueProp?: string;
    filterable?: boolean; // 是否可搜索过滤
    show?: boolean;
  }>(),
  {
    columns: 4,
    labelProp: "label",
    valueProp: "value",
  }
);
const isShow = computed(() =>{
  if (props.show) return true;
    if (index < 6) return true;
    else return false;
})
const datalist = computed(() => {
  return props.options.filter((e, index) => {
    if (props.show) return true;
    else if (!props.show && index < 6) return true;
    else return false;
  });
});

const emits = defineEmits<{
  (event: "update:modelValue", value: any): void;
  (event: "change", value: any, option?: OptionType | OptionType[]): void;
  (event: "keywordChanged");
}>();

const keywords = ref("");

const searchOptions = computed(() => {
  if (!keywords.value.trim()) {
    return [];
  }
  return props.options.filter((e) => {
    return getLabel(e)?.includes(keywords.value.trim());
  });
});

const [emitKeywordChanged] = useDebounce(() => {
  emits("keywordChanged");
}, 300);

const getLabel = (option: OptionType) => {
  return option[props.labelProp] as string;
};

const getValue = (option: OptionType) => {
  return option[props.valueProp];
};

const isSelected = (option: OptionType): boolean => {
  if (props.multiple) {
    return (props.modelValue || []).find((e) => e == getValue(option));
  }
  // console.log('props.modelValue ', props.modelValue);
  // console.log('getValue(option) ', getValue(option));
  // console.log('props.modelValue == getValue(option)', props.modelValue == getValue(option));
  return props.modelValue == getValue(option);
};

const onClick = (option: OptionType) => {
  if (props.multiple) {
    const has = isSelected(option);
    if (!has) {
      // 限制选择数量
      if (props.multipleLimit) {
        if ((props.modelValue?.length ?? 0) >= props.multipleLimit) {
          return;
        }
      }
    }

    const newValue = has
      ? (props.modelValue || []).filter((e) => e != getValue(option))
      : [...(props.modelValue || []), getValue(option)];

    emits("update:modelValue", newValue);
    emits(
      "change",
      newValue,
      (props.options || []).filter((e) => newValue.indexOf(e.value) >= 0)
    );
  } else {
    if (getValue(option) == props.modelValue) {
      emits("update:modelValue", null);
      emits("change", null, undefined);
    } else {
      emits("update:modelValue", getValue(option));
      emits("change", getValue(option), option);
    }
  }
};
</script>

<style lang="scss" scoped>
.search {
  font-size: 10px;
  color: #3b3944;
  background: #f8f9fb;
  border-radius: 50px;
  border: 1px solid #f0f0f0;
  padding: 0 10px;
  height: 56rpx;
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 10px;
  .icon {
    width: 15px;
    height: 15px;
  }
  .search-input {
    flex: 1;
    height: 100%;
  }
}
.empty {
  text-align: center;
  margin-bottom: 20px;
  .image {
    width: 99px;
    height: 99px;
  }
  .text {
    display: flex;
    justify-content: center;
    font-size: 12px;
    color: #696969;
    white-space: nowrap;
    overflow: hidden;
    .keywords {
      color: #fdab27;
      text-overflow: ellipsis;
    }
  }
}
.grid-select {
  display: flex;
  gap: 16px;
  flex-wrap: wrap;

  &.search-select {
    margin-bottom: 12px;
  }

  .option {
    width: 30%;
    display: flex;
    align-items: center;
    text-align: center;
    justify-content: center;
    height: 40px;
    border-radius: 4px;
    padding: 0 4px;
    font-size: 13px;
    font-weight: 400;
    color: #3b3944;
    background: #f6f7f9;
    overflow: hidden;
    box-sizing: border-box;

    &.selected {
      background: #ffc8c7;
      color: #bb3d34;
    }
  }
}
</style>
